package org.example.service.impl;

import com.aspose.pdf.Document;
import com.aspose.pdf.SaveFormat;
import com.benjaminwan.ocrlibrary.OcrResult;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import io.github.mymonstercat.Model;
import io.github.mymonstercat.ocr.InferenceEngine;
import io.github.mymonstercat.ocr.config.ParamConfig;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.example.service.IRapidOcrService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

@Service
public class RapidOcrServiceImpl implements IRapidOcrService {

    /**
     * 将pdf转换为图片
     *
     * @param file
     * @return List<String>
     */
    @Override
    public List<String> pdfToImage(MultipartFile file) {
        long startTime = System.currentTimeMillis();
        List<String> imagePaths = new ArrayList<>();

        // 临时存储上传的 PDF 文件
        File tempFile = null;

        try {
            // 将 MultipartFile 转为临时文件
            tempFile = File.createTempFile("tempPdf", ".pdf");
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                fos.write(file.getBytes());
            }

            // 加载 PDF 文件
            PDDocument doc = Loader.loadPDF(tempFile);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();

            // 获取 resources/images 目录路径
            String imagesDir = Paths.get("src/main/resources/images").toAbsolutePath().toString();
            File dir = new File(imagesDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }

            for (int i = 0; i < pageCount; i++) {
                // 将 PDF 页渲染为图片，DPI 设置为 300
                BufferedImage image = renderer.renderImageWithDPI(i, 300);
                // 设置图片文件名
                String imageName = file.getOriginalFilename().replace(".pdf", "") + "-" + (i + 1) + ".png";
                File outputFile = new File(imagesDir, imageName);
                ImageIO.write(image, "png", outputFile);

                // 将图片的绝对路径添加到集合中
                imagePaths.add(outputFile.getAbsolutePath());
            }

            doc.close();
            long endTime = System.currentTimeMillis();
            System.out.println("共耗时：" + ((endTime - startTime) / 1000.0) + "秒");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 删除临时文件
            if (tempFile != null && tempFile.exists()) {
                tempFile.delete();
            }
        }

        return imagePaths; // 返回所有图片的绝对路径
    }

    /**
     * 执行OCR识别
     *
     * @param imgPaths
     * @return
     */
    @Override
    public String doOcr(List<String> imgPaths) {
        // 创建识别参数对象
        ParamConfig paramConfig = ParamConfig.getDefaultConfig();
        // 开启文本方向检测
        paramConfig.setDoAngle(true);
        // 开启角度投票(整张图片以最大可能文字方向来识别)
        paramConfig.setMostAngle(true);
        // 创建并指定识别引擎
        InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V3);
        // 创建识别后的结果集合
        List<String> result = new ArrayList<>();
        // 循环识别图片提取出文字
        for (String path : imgPaths) {
            OcrResult ocrResult = engine.runOcr(path, paramConfig);
            result.add(ocrResult.getStrRes());
        }
        // 将所有识别结果合并
        StringBuilder sb = new StringBuilder();
        for (String s : result) {
            sb.append(s);
        }
        return sb.toString();
    }

    /**
     * 执行单张图片识别
     *
     * @param fileUpload
     * @return
     */
    @Override
    public String doImageOcr(MultipartFile fileUpload) {
        // 创建识别参数对象
        ParamConfig paramConfig = ParamConfig.getDefaultConfig();
        // 开启文本方向检测
        paramConfig.setDoAngle(true);
        // 开启角度投票(整张图片以最大可能文字方向来识别)
        paramConfig.setMostAngle(true);
        // 创建并指定识别引擎
        InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V3);
        // 图片保存路径
        String savePath = System.getProperty("user.dir") + "/imgTemp/" + fileUpload.getOriginalFilename();
        File file = new File(savePath);

        // 检查目录是否存在，如果不存在则创建
        File directory = new File(file.getParent());
        if (!directory.exists()) {
            directory.mkdirs(); // 创建所有必要的父目录
        }

        try {
            fileUpload.transferTo(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        file.deleteOnExit();
        OcrResult ocrResult = engine.runOcr(file.getPath(), paramConfig);
        return ocrResult.getStrRes().toString();
    }

    /**
     * 将pdf转换为word
     * @param file
     * @param response
     */
    @Override
    public void pdfToWord(MultipartFile file, HttpServletResponse response) throws UnsupportedEncodingException {
        response.reset();
        String originalFilename = file.getOriginalFilename();
        String docxFilename = originalFilename != null ? originalFilename.replaceAll("\\.pdf$", ".docx") : "converted.docx";

        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(docxFilename, "UTF-8"));
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        response.setContentType("application/x-msdownload");

        long old = System.currentTimeMillis();
        try (OutputStream outputStream = response.getOutputStream();
             InputStream inputStream = file.getInputStream()) {

            Document doc = new Document(inputStream);
            doc.save(outputStream, SaveFormat.DocX);

        } catch (Exception e) {
            System.out.println("Pdf 转 Word 失败...");
            e.printStackTrace();
        }
        long now = System.currentTimeMillis();
        System.out.println("Pdf 转 Word 共耗时：" + ((now - old) / 1000.0) + "秒");
    }

    /**
     * 将Word文档转换为PDF文件
     *
     * @param file  输入Word文件路径
     * @param response 响应对象
     * @return 转换是否成功
     */
    @Override
    public boolean convertWordToPdf(MultipartFile file, HttpServletResponse response) {
        String originalFileName = file.getOriginalFilename();
        if (originalFileName == null || (!originalFileName.endsWith(".docx") && !originalFileName.endsWith(".doc"))) {
            throw new IllegalArgumentException("必须上传一个有效的 Word 文件（.doc 或 .docx）");
        }

        // 生成 PDF 文件名
        String pdfFileName = originalFileName.replace(".docx", ".pdf").replace(".doc", ".pdf");

        // 设置响应类型
        response.setContentType("application/pdf");

        try {
            // URL 编码文件名
            String encodedFileName = URLEncoder.encode(pdfFileName, StandardCharsets.UTF_8.toString());
            // 设置 Content-Disposition 头
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("文件名编码异常: " + e.getMessage(), e);
        }

        try (InputStream doc = file.getInputStream();
             OutputStream outputStream = response.getOutputStream()) {

            IConverter converter = LocalConverter.builder().build();
            DocumentType sourceType = DocumentType.MS_WORD;

            boolean success = converter.convert(doc)
                    .as(sourceType)
                    .to(outputStream)
                    .as(DocumentType.PDF)
                    .execute();

            converter.shutDown();
            return success;

        } catch (IOException e) {
            System.err.println("IO异常: " + e.getMessage());
        }

        return false;
    }

}
